package com.augrain.microframework.lock;

import com.augrain.microframework.lock.config.DLockConfig;
import com.augrain.microframework.lock.core.BusinessKeyProvider;
import com.augrain.microframework.lock.core.DLockAspectHandler;
import com.augrain.microframework.lock.core.LockInfoProvider;
import com.augrain.microframework.lock.lock.LockFactory;
import io.netty.channel.nio.NioEventLoopGroup;
import jakarta.annotation.Resource;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.client.codec.Codec;
import org.redisson.config.Config;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.util.ClassUtils;

/**
 * 基于Redis的分布式锁
 *
 * @author biaoy
 * @since 2020/12/04
 */
@Configuration
@ConditionalOnProperty(prefix = DLockConfig.PREFIX, name = "enable", havingValue = "true", matchIfMissing = true)
@AutoConfigureAfter(RedisAutoConfiguration.class)
@EnableConfigurationProperties(DLockConfig.class)
@Import({DLockAspectHandler.class})
public class DLockAutoConfiguration implements BeanPostProcessor {

    @Resource
    private DLockConfig dLockConfig;

    @Bean(destroyMethod = "shutdown")
    @ConditionalOnMissingBean
    RedissonClient redisson() throws Exception {
        Config config = new Config();
        if (dLockConfig.getClusterServer() != null) {
            config.useClusterServers().setPassword(dLockConfig.getPassword())
                    .addNodeAddress(dLockConfig.getClusterServer().getNodeAddresses());
        } else {
            config.useSingleServer().setAddress(dLockConfig.getAddress())
                    .setDatabase(dLockConfig.getDatabase())
                    .setPassword(dLockConfig.getPassword());
        }
        Codec codec = (Codec) ClassUtils.forName(dLockConfig.getCodec(), ClassUtils.getDefaultClassLoader()).newInstance();
        config.setCodec(codec);
        config.setEventLoopGroup(new NioEventLoopGroup());
        RedissonClient redissonClient = Redisson.create(config);

        // 设置RedissonClient对象到LockFactory中
        LockFactory.setRedissonClient(redissonClient);

        return redissonClient;
    }

    @Bean
    public LockInfoProvider lockInfoProvider() {
        return new LockInfoProvider();
    }

    @Bean
    public BusinessKeyProvider businessKeyProvider() {
        return new BusinessKeyProvider();
    }
}
